import encode from 'encode-3986'

/** @type {Object} 助手方法 */
const util = {
  toStr: Object.prototype.toString,
  isUndef: function(v) {
    return v === undefined || v === null;
  },
  isDef: function(v) {
    return v !== undefined && v !== null;
  },
  isTrue: function(v) {
    return v === true;
  },
  isFalse: function(v) {
    return v === false;
  },
  // 检测对象类型
  isRegExp: function(v) {
    return this.toStr.call(v) === '[object RegExp]';
  },
  isArray: function(v) {
    return this.toStr.call(v) === '[object Array]';
  },
  isString: function(v) {
    return this.toStr.call(v) === '[object String]';
  },
  isObject: function(v) {
    return this.toStr.call(v) === '[object Object]';
  },
  isEmptyObject: function(v) {
    return Object.keys(v).length === 0
  },
  isJson: function(v) {
    return this.isObject(v) && v.constructor == Object;
  },
  isFunction: function(v) {
    return this.toStr.call(v) === '[object Function]';
  },
  isNumber: function(v) {
    return this.toStr.call(v) === '[object Number]';
  },
  isDate: function(v) {
    return this.toStr.call(v) === '[object Date]';
  },
  inArray: function(search, array) {
    for (var i in array) {
      if (array[i] == search) {
        return true;
      }
    }
    return false;
  },
  // 删除数组中某一个
  remove: function(arr, item) {
    if (arr.length) {
      var index = arr.indexOf(item);
      if (index > -1) {
        return arr.splice(index, 1);
      }
    }
    return arr;
  },
  matches: function(pattern, name) {
    if (Array.isArray(pattern)) {
      return pattern.indexOf(name) > -1;
    } else if (typeof pattern === 'string') {
      return pattern.split(',').indexOf(name) > -1;
    } else if (this.isRegExp(pattern)) {
      return pattern.test(name);
    }
    return false;
  },
  /**
   * todo
   */
  isapp: function() {
    if (process.env.NODE_ENV === 'production') {
      // return navigator.userAgent.toLowerCase().indexOf(projectTag) >= 0;
      return navigator.userAgent.toLowerCase().indexOf('micromessenger') < 0;
    }
    return false;
  },
  moneyFilter: function(text) {
    if (text.indexOf('.') >= 0) {
      return text.split('.')[0] - 0;
    }
    return text - 0;
  },
  isIPhoneX: function() {
    // iPhone X、iPhone XS
    return /iphone/gi.test(window.navigator.userAgent) && window.devicePixelRatio && window.devicePixelRatio === 3 &&
      window.screen.width === 375 && window.screen.height === 812;
  },
  isIPhoneXSMax: function() {
    // iPhone XS Max
    return /iphone/gi.test(window.navigator.userAgent) && window.devicePixelRatio && window.devicePixelRatio === 3 &&
      window.screen.width === 414 && window.screen.height === 896;
  },
  isIPhoneXR: function() {
    // iPhone XR
    return /iphone/gi.test(window.navigator.userAgent) && window.devicePixelRatio && window.devicePixelRatio === 2 &&
      window.screen.width === 414 && window.screen.height === 896;
  },
  IPhoneX: function() {
    return this.isIPhoneX() || this.isIPhoneXSMax() || this.isIPhoneXR();
  },
  /**
   * 获取IE浏览器版本
   * @Author   Martinsun<syh@sunyonghong.com>
   * @DateTime 2020-02-16
   */
  IEVersion: function() {
    var userAgent = navigator.userAgent; // 取得浏览器的userAgent字符串
    var isIE = userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1; // 判断是否IE<11浏览器
    var isEdge = userAgent.indexOf('Edge') > -1 && !isIE; // 判断是否IE的Edge浏览器
    var isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf('rv:11.0') > -1;
    if (isIE) {
      var reIE = new RegExp('MSIE (\\d+\\.\\d+);');
      reIE.test(userAgent);
      var fIEVersion = parseFloat(RegExp['$1']);
      if (fIEVersion == 7) {
        return 7;
      } else if (fIEVersion == 8) {
        return 8;
      } else if (fIEVersion == 9) {
        return 9;
      } else if (fIEVersion == 10) {
        return 10;
      } else {
        return 6; // IE版本<=7
      }
    } else if (isEdge) {
      return 'edge'; // edge
    } else if (isIE11) {
      return 11; // IE11
    } else {
      return -1; // 不是ie浏览器
    }
  },
  /**
   * 将数据转为json字符串
   * @Author   Martinsun<syh@sunyonghong.com>
   * @DateTime 2020-02-16
   * @param    {string} str 初始数据
   * @return   {string}
   */
  toJson: function(str) {
    return JSON.stringify(str);
  },
  /**
   * 转为数组类型
   * @Author   Martinsun<syh@sunyonghong.com>
   * @DateTime 2019-09-25
   * @param    obj|array  obj    原始数据
   * @param    undefined|true  format 是否需要转换,指定为true时,进行数据转换
   * @return   array
   */
  toArray: function(obj, format) {
    if (!this.isArray(obj)) {
      return [];
    }
    if (this.isTrue(format)) {
      var _obj = [];
      for (const i in obj) {
        _obj.push({
          [i]: obj[i]
        });
      }
      return _obj;
    }
    return obj;
  },
  /**
   * 将首字母转为大写
   * @Author   Martinsun<syh@sunyonghong.com>
   * @DateTime 2020-02-16
   * @param    {string} str 字符串数据
   * @return   {string}
   */
  ucfirst: function(str) {
    var arr = str.toLowerCase().split(' '); // 字符串以空格为界限转换为数组
    for (var i = 0; i < arr.length; i++) {
      arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].slice(1); // charAt()方法得到第一个字母，slice()得到第二个字母以后的字符串
    }
    // 合并数组为字符串
    str = arr.join(' ')
    return str
  },
  /**
   * 清除字符串两端空格，包含换行符、制表符
   */
  trim: function(str) {
    return str.replace(/(^[\s\n\t,]+|[\s\n\t,]+$)/g, '');
  },
  /**
   * 清除字符串左侧空格，包含换行符、制表符
   */
  ltrim: function(str) {
    return str.replace(/^[\s\n\t,]+/g, '');
  },
  /**
   * 清除字符串右侧空格，包含换行符、制表符
   */
  rtrim: function(str) {
    return str.replace(/[\s\n\t,]+$/g, '');
  },
  /**
   * 合并资源
   * @Author   Martinsun<syh@sunyonghong.com>
   * @DateTime 2020-02-16
   * @param    {object|array} source 原始资源
   * @param    {object|array} target 对比数据
   * @return   无返回值,直接改变source
   */
  extend: function(source, target) {
    for (var key in target) {
      if (source[key] === undefined) { // 不冲突的，直接赋值
        source[key] = target[key];
        continue;
      }
      var isJson = this.isJson(target[key]);
      if (!this.isJson(source[key]) && isJson) {
        source[key] = {};
      }
      // 冲突了，如果是Object，看看有么有不冲突的属性
      // 不是Object 则以main为主，忽略即可。故不需要else
      if (isJson) {
        // arguments.callee 递归调用，并且与函数名解耦
        /*eslint-disable*/
        arguments.callee(source[key], target[key]);
      } else {
        // if (this.isFunction(target[key]))
        source[key] = target[key];
      }
    }
  },
  getDefValue(value, _default) {
    if (this.isDef(value)) {
      return value;
    }

    return _default;
  },
  // 排序的函数
  objKeySort(arys) {
    // 先用Object内置类的keys方法获取要排序对象的属性名数组，再利用Array的sort方法进行排序
    var newkey = Object.keys(arys).sort();
    var newObj = ''; // 创建一个新的对象，用于存放排好序的键值对
    for (var i = 0; i < newkey.length; i++) {
      if (util.isDef(arys[newkey[i]]) && arys[newkey[i]] !== null && arys[newkey[i]] !== '') {
        // 遍历newkey数组
        var value = (util.isArray(arys[newkey[i]]) || util.isObject(arys[newkey[i]])) ? '/a' : arys[newkey[i]];
        newObj += [newkey[i]] + '=' + value + '&';
      }
    }

    return encode(newObj.substring(0, newObj.length - 1));
  },
  // 深拷贝对象
  deepClone(obj) {
    const _toString = Object.prototype.toString

    // null, undefined, non-object, function
    if (!obj || typeof obj !== 'object') {
      return obj
    }

    // DOM Node
    if (obj.nodeType && 'cloneNode' in obj) {
      return obj.cloneNode(true)
    }

    // Date
    if (_toString.call(obj) === '[object Date]') {
      return new Date(obj.getTime())
    }

    // RegExp
    if (_toString.call(obj) === '[object RegExp]') {
      const flags = []
      if (obj.global) {
        flags.push('g')
      }
      if (obj.multiline) {
        flags.push('m')
      }
      if (obj.ignoreCase) {
        flags.push('i')
      }

      return new RegExp(obj.source, flags.join(''))
    }

    const result = Array.isArray(obj) ? [] : obj.constructor ? new obj.constructor() : {}

    for (const key in obj) {
      result[key] = util.deepClone(obj[key])
    }

    return result
  },
  /**
   * Parse the time to string
   * @param {(Object|string|number)} time
   * @param {string} cFormat
   * @returns {string | null}
   */
  parseTime(time, cFormat = '{y}-{m}-{d} {h}:{i}') {
    if (arguments.length === 0 || !time) {
      return null
    }
    const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
    let date
    if (typeof time === 'object') {
      date = time
    } else {
      if ((typeof time === 'string')) {
        if ((/^[0-9]+$/.test(time))) {
          // support "1548221490638"
          time = parseInt(time)
        } else {
          // support safari
          // https://stackoverflow.com/questions/4310953/invalid-date-in-safari
          time = time.replace(new RegExp(/-/gm), '/')
        }
      }

      if ((typeof time === 'number') && (time.toString().length === 10)) {
        time = time * 1000
      }
      date = new Date(time)
    }
    const formatObj = {
      y: date.getFullYear(),
      m: date.getMonth() + 1,
      d: date.getDate(),
      h: date.getHours(),
      i: date.getMinutes(),
      s: date.getSeconds(),
      a: date.getDay()
    }
    return format.replace(/{([ymdhisa])+}/g, (result, key) => {
      const value = formatObj[key]
      // Note: getDay() returns 0 on Sunday
      if (key === 'a') {
        return ['日', '一', '二', '三', '四', '五', '六'][value]
      }
      return value.toString().padStart(2, '0')
    })
  },

  /**
   * @param {number,string} time
   * @param {string} option
   * @param defaultFormat
   * @returns {string}
   */
  formatTime(time, option = null) {
    if(!util.isString(time)) {
      if (('' + time).length === 10) {
        time = parseInt(time) * 1000
      } else {
        time = +time
      }
    }
    const d = new Date(time)
    const now = Date.now()

    const diff = (now - d) / 1000

    if (diff < 30) {
      return '刚刚'
    } else if (diff < 3600) {
      // less 1 hour
      return Math.ceil(diff / 60) + '分钟前'
    } else if (diff < 3600 * 24) {
      return Math.ceil(diff / 3600) + '小时前'
    } else if (diff < 3600 * 24 * 2) {
      return '1天前'
    }
    if (option) {
      return util.parseTime(time, option)
    } else {
      const formatObj = {
        y: d.getFullYear(),
        m: d.getMonth() + 1,
        d: d.getDate(),
        h: d.getHours(),
        i: d.getMinutes(),
        s: d.getSeconds()
      }
      const now = new Date()

      return (
          (formatObj.y === now.getFullYear() ? '' : formatObj.y + '年') +
          formatObj.m + '月' +
          formatObj.d + '日 '
          // formatObj.h + '时' +
          // formatObj.i + '分'
      );
    }
  },
  /**
   * 格式化学习时长
   * @param time
   * @param unit
   * @returns {{hour: number, day: number, minute: number}}
   */
  learnTime(time, unit) {
    if (!this.isNumber(time)) time = 0

    if (unit === 'sec') {
      time = time / 60
    } else {
      time = +time
    }

    let day = Math.floor(time / (24 * 60))
    let hour = Math.floor((time - day * 24 * 60) / 60)
    let minute = Math.floor(time - day * 24 * 60 - hour * 60)

    return {
      day,
      hour,
      minute
    }
  },
}

export default util
